Разработка навигационной программы

Gmurik2, в таком случае я не понимаю, каким образом Q-tree используется для построения маршрута.

Я так понял оно не столько для построения маршрута используется, сколько для быстрого поиска нужных узлов графа по которым в дальнейшем ведется поиск маршрута.

В первой таблице явно ошибки со смещением. Следует посмотреть в районе 2 и 22 байтов.
Кроме того, я бы настоятельно рекомендовал использовать поля, выравненные на границу 4. Иначе с обработкой на 32-разрядных процессорах будут большие проблемы.
Коль скоро для координат используется int32, следовало бы указать, каким координатам (в вещественных градусах) соответствуют какие целые числа. Т.е. формулы преобразования.
Слово “адрес” обычно применяется к адресации в оперативной памяти. При этом реальное значение адреса заранее неопределено и определяется менеджером памяти. В файле же присутствуют смещения - фиксированные величины относительно начала файла либо начала блока.
Непонятно, что находится между “30” и “30+(Количество графов)*4”.
Смещения во всех таблицах даются от 0, что принимается за 0? Надеюсь, не начало файла? Вероятно, это начало заголовка, тогда хотелось бы, чтобы явно было указано, где хранится адрес данного заголовка.
И еще: как разбирать поля, для которых указано n/a? Вероятно, если этому препятствует структура Qstring, то надо от нее отказаться, чтобы снять неопределенность в формате файла.
Кстати, что все-таки такое Qstring?

Увы, пока не стало.

А можно поинтересоваться какие?

Формула примитивна до ужаса lat = int32/10000000
так пока и не придумал как отойти от вещественных вычислений, Есть предложения получше?

Этому препятствует то, что заранее нельзя знать длину QString.
QString это строка в UTF-8, при записи в файл, сначала указывается длина строки в байтах, а далее идет собственно строка по 2 байта на символ.

Скорость: два чтения памяти вместо одного.

Обычно переводят в целые числа по-другому: ilat = int( lat / 90 * 2^31 ), ilon = int( lon / 180 * 2^ 31 )

64-битные целые это уже насущная необходимость

Точность в семь знаков, после запятой я считаю более чем достаточна для навигатора, тем более исходные данные так же содержат 7 знаков после запятой.

Gmurik2, речь о том что с бинарными долями окружности работать будет удобнее, чем с десятичными долями градусов.

Пока не вижу удобств… Переделать не долго…

Есть небольшие продвижения, ознакомиться можно здесь

Внимание! Присутствует проблема утечки память. И не оптимизирован вывод quad’ов, так что при перемещении карты есть тормоза. Ну как говорится лед тронулся :slight_smile:

Она скомпилена в дебажном режиме и требует QtCored4.dll

А ещё msvcp71d.dll и msvcr71d.dll
У меня так и не запустилась.

На нормальных процессорах адресация ведется по словам, а не по байтам. Представь, что тебе на архитектуре Intel пришлось бы читать данные, в которых байты расположены не каждый по своему адресу, а 3 бита по одному адресу и 5 - по соседнему. А потом из этих фрагментов собирать нужные тебе байты.
Вот на 32-разрядной архитектуре примерно так надо будет работать с невыравненными данными.

На мой взгляд, наиболее естественным был бы вариант lat=int32/2147483647*180.0. Компьютер ведь работает в двоичной, а не десятичной системе.

Кошмар!
При такой организации данные будут КАТАСТРОФИЧЕСКИ медленно читаться, т.к. вменяемая буферизация их будет крайне затруднена.
В такой ситуации следует собирать все строки переменной длины в отдельный массив, а в заголовке указывать только смещение в этом массиве (или в файле), чтобы заголовок имел фиксированную длину. Иначе на файловых операциях потеряешь в производительности порядки.

Для компактных систем (типа навигаторов, КПК и телефонов) это пока неактуально.
Кстати, в заголовке я не обнаружил ни одного int64, с чего бы это? :wink:

Извиняюсь, что влезаю в середину разговора. Но вообще-то такая организация файла работу никак не замедлит. При чтении байтов из файла как правило читается сразу блок данных, чтобы как раз избежать проблем со скоростью. Так называемое “упреждающее чтение”. Так что такое хранение никаких на скорость не повлияет.

P.S. Ещё раз извиняюсь, если сказал что-то совсем неверное. Попробовал найти обсуждение этого куска в предыдущих мессагах. Не получилось. :frowning: Так что надеюсь я правильно понял суть высказываний andriano

P.S.S.Влез в тему, так как увидел знакомые слова про фиксированную математику, которая последнее время ненавижу всё больше. :slight_smile:

Мне несколько лениво перечитывать весь тред. Речь идет о формате файла или о формате данных в оперативке. Если про файл, то при чем тут вообще адресация RAM? Не надо никакого выравнивания в файлах. Если про выравнивание в операвке, то компилятор лучше вас знает, что и как выравнивать. Например для ARM местами надо на 8 байт выравнивать.

Вы сами буферизацию собираетесь писать? Или все-таки доверите это glibc и ОС? Кстати, упреждающее чтение работает намного лучше, если данные одним куском, а не размазаны по файлу. А на то, одинаковой ли длинны записи, glibc и ОС пофиг, они про эти самые записи ничего не знают.

А еще файл можно засунуть в память операцией memmap. И тогда замечательно будет работать кэширование в памяти блоков, к которым доступ производится наиболее часто (конкретная стратегия зависит от ОС).

Обратите внимание, что замыкание координат при переходе через 180 меридиан получается автоматически за счет overflow. И в полной мере используется диапазон допустимых значений целочисленного типа.

P.S. Надо сделать typedef int32_t CoordType и в случае надобности можно будет использовать другой тип. Аналогично поступить со всякими идентификаторами и смещениями в файлах.
P.P.S. В stdint.h объявлены платформонезависимые типы uint32_t uint64_t int32_t int64_t и т.д.

Угу, только он не часть стандарта С++ и под виндой не во всех компиляторах доступен from the box.

Скачал с сайта NaviGOSM_prealpfa_0.1.7z
Не запускается.
Требует QtCored4.dll

p.s. судя по всему собрал проект в отладочном режиме

Но ведь лучше для этих компиляторов добавить этот файл, чем полагаться, скажем, на то что int имеет разрадность 32 бита или что char всегда unsigned. Есть архитектуры, где это не так. А писать свой аналог stdint.h я не вижу смысла. А так, M_PI тоже не часть стандарта. Не отказываться же от него из-за этого не вводить во всех своих проектах свою собственную константу.

Надо-надо. Хоть функции общения с диском и обвешены костыликам, чтобы пользователь не догадался, что они 32-битные и им удобнее работать с выравненными данными, лучше этим не пользоваться и всё везде равнять.

Э-э-э… Какой-такой ARM с 8 байтным варавниванием?
Я, правда, 11-ые не видел, как и кортексы-А, но вряд-ли там что-то новое…

Ладно. Что-то мы не в ту степь полезли…

В svn какая-то странная структура каталогов. Сначала каталоги по приложениям, а в каждом из них каталог trunk. Обычно делают наоборот: trunk, а в нем каталоги по приложениям. А самое главное, что пути в файлах прописаны с расчетом на второй вариант и в результате, если я выгружаю файлы из svn, ничего не собирается т.к. не может найти файлы.

#include "geometry.h"

mapview.h:7:22: error: geometry.h: Нет такого файла или каталога
mapview.h:8:24: error: navigo_api.h: Нет такого файла или каталога
mapview.h:9:30: error: quadro_tree_node.h: Нет такого файла или каталога

Или #include <geometry.h> или надо указывать относительные пути.
Лирическое отсупление: Предлагаю закидать помидорами того придурка, который когда-то решил выпендриться и использовать в качетсве разделителей каталогов специальный символ \ вместо общепринятого /

Меня смущает обилие warning’ов выдаваемых компилятором. На них надо обращать внимание, их быть не должно вообще (ну только в совсем исключительных случаях).

    const qint32 getLeft() { return Left; }

Ты возвращаешь const qint32, а сама функция у тебя отнюдь не константная.


class Bound : public QObject
{
    Q_OBJECT

Зачем этот класс унаследован от QObject? Он не использует ни слоты, ни сигналы. Ему вообще не надо ни от чего наследоваться и быть виртуальным.


    void *setUl(quadro_tree_node *tree) {ul = tree;} // верхний левый

Она же ничего не возвращает. И в целом, аккуратнее с void*. Это хак в стиле C, а в C++ так не делают (только в крайнем случае, если наследование не справляется, например в boost::prt_container).

Я бы рекомендовал использовать для файлов кодировку utf-8, а не cp1251. С utf-8 сейчас намного меньше проблем, чем с cp1251. Там более странно выглядит программа, во всю использующая utf-8 но закодированная в cp1251.


private:
....
    quadro_tree_node *ul; // верхний левый
    quadro_tree_node *ur; // верхний правый
    quadro_tree_node *dr; // нижний правый
    quadro_tree_node *dl; // нижний левый

    bool sheet;
    QList<geometry *> geometrys;


quadro_tree_node::quadro_tree_node(const qint32 minlat, const qint32 maxlat,
                                   const qint32 minlon, const qint32 maxlon,
                                   const qint32 max_size) : ul(0), ur(0), dl(0), dr(0), size_sheet(max_size) {
    setTreeNode(minlat, maxlat, minlon, maxlon);
}

И тут подлая setTreeNode кидает exception и конструктор деструктор не вызывается… Используй std::auto_ptr. И для остальных ресурсов рулят умные контейнеры, которые сами удалят хранимое при уничтожении. Иначе обрабатывать исключения очень неудобно.


quadro_tree_node::~quadro_tree_node() {
...
    geometrys.clear();

Это удалит сами указатели, но не объекты, на которые они указывают. Ты этого хотел?

На этом сборка оборвалась.

P.S. Делай typedef для основных используемых типов, а именно координат, идентификаторов. Потом можно будет легко сменить.
P.P.S. quint32 также хорошо, как и int32_t.

А можно ссылку на какую-нибудь статью. Данные в файле все равно выравняны не так, как в памяти и нам нужно их оттуда считать сначала в буфер (это сделает glibc и ОС), а затем из буфера уже скопировать в нужные поля структуры. В худшем случае процессор сделает в два раза больше чтений из буфера (считывая каждое невыровнянное значение двумя кусками). Это же ничтожно мало по сравнению со временем, которое эти данные будут читаться с диска. Кроме того, читая кусок из буфера, даже невыровнянный, мы загрузим его в кэш процессора, и во второй раз (когда будет читаться вторая часть из считанного куска), он уже будет в кэше и считается быстро.
Если же начинаем выравнивать, то у нас возникают дырки, которые тоже надо считать с диска и потратить на это время.

Поэтому хотелось бы ссылку на какие-нибудь исследования/измерения, чтобы понять каков эффект.

Я давно с ARM возился. Возникало на ARM v4 (такой стоял на моем asus A620). Тогда только вводили EABI:
http://wiki.debian.org/ArmEabiPort
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4127.html

Поэтому я переложил это на плечи Qt и использую типы qint32 и т.д.

Да хотел этого, но в Qt есть макрос qDeleteAll который делает тоже самое, поправил, спасибо за подсказку :slight_smile:

Перед сборкой собственно NaviGOSM, необходимо собрать NaviGO_API и указать в .pro файле путь до сборки NaviGO_API.

Да моя не внимательность Debug dll в архив запихнул, исправил вроде :slight_smile: